package com.wht.sip.service.impl;

import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.wht.sip.config.MediaConfig;
import com.wht.sip.config.SipConfig;
import com.wht.sip.core.context.SipProcessorContext;
import com.wht.sip.core.transmit.SIPSender;
import com.wht.sip.core.transmit.model.Device;
import com.wht.sip.service.DeviceService;
import com.wht.sip.utils.IpPortUtil;
import com.wht.sip.utils.SipUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.noear.snack.ONode;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Managed;

import javax.sip.SipFactory;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.Request;
import java.util.ArrayList;

/**
 * @author by HaiTao.Wang on 2025/9/18.
 */
@Slf4j
@Managed
public class DeviceServiceImpl implements DeviceService {

    @Inject
    SipConfig sipConfig;

    @Inject
    MediaConfig mediaConfig;

    @Inject
    SIPSender sipSender;

    @SneakyThrows
    @Override
    public String play(String deviceId) {

        Device device = SipProcessorContext.deviceMap.get(deviceId);
        if (device == null) {
            log.info("设备：{} 不存在", deviceId);
            return "";
        }

        //构建INVITE消息报文

        // SDP部分
        StringBuilder content = new StringBuilder(200);
        content.append("v=0\r\n");
        content.append("o=").append(deviceId).append(" 0 0 IN IP4 ").append(mediaConfig.getIp()).append("\r\n");
        content.append("s=Play\r\n");
        content.append("c=IN IP4 ").append(mediaConfig.getIp()).append("\r\n");
        content.append("t=0 0\r\n");

        // 1.开启rtp服务
        String response = HttpRequest.post(mediaConfig.getRtp())
                .body(
                        JSONUtil.createObj()
                                //系统自动分配端口
                                .set("port", 0)
                                .set("tcpMode", 1)
//                                .set("stream", deviceId)
                                .set("stream", "34020000001110000002")
                                .toString()
                )
                .execute()
                .body();

        // rtp端口号
        int rtpPort = ONode.load(response).get("data").getInt();

        // tcp
        content.append("m=video ").append(rtpPort).append(" TCP/RTP/AVP 96 97 98 99\r\n");
//        //udp
//        content.append("m=video ").append(rtpPort).append(" RTP/AVP 96 97 98 99\r\n");
        content.append("a=recvonly\r\n");
        content.append("a=rtpmap:96 PS/90000\r\n");
        content.append("a=rtpmap:98 H264/90000\r\n");
        content.append("a=rtpmap:97 MPEG4/90000\r\n");
        content.append("a=rtpmap:99 H265/90000\r\n");

        // tcp被动模式
        content.append("a=setup:passive\r\n");
        content.append("a=connection:new\r\n");

        // tcp主动模式
//        content.append("a=setup:active\r\n");
//        content.append("a=connection:new\r\n");

        //音频
//        content.append("m=audio ").append(rtpPort).append(" TCP/RTP/AVP 0 8\r\n");
//        content.append("a=recvonly\r\n");
//        content.append("a=rtpmap:0 PCMU/8000\r\n");
//        content.append("a=rtpmap:8 PCMA/8000\r\n");

        // 0点播 1录播
        String ssrc = 0 + sipConfig.getDomain().substring(3, 8) + RandomUtil.randomNumbers(4);
        content.append("y=").append(ssrc).append("\r\n");

        // 2.构建INVITE请求
        Request request;
        //请求行
        SipURI requestLine = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
        //via
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader viaHeader = SipFactory.getInstance().createHeaderFactory().createViaHeader(NetUtil.getLocalhostStr(), sipConfig.getPort(), "UDP", SipUtils.getNewViaTag());
        viaHeader.setRPort();
        viaHeaders.add(viaHeader);

        //from
        SipURI fromSipUri = SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), sipConfig.getDomain());

        Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipUri);
        //必须要有标记，否则无法创建会话，无法回应ack
        FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, SipUtils.getNewFromTag());

        //to
        SipURI toSipUri = SipFactory.getInstance().createAddressFactory().createSipURI(device.getDeviceId(), device.getHostAddress());
        Address toAddress = SipFactory.getInstance().createAddressFactory().createAddress(toSipUri);
        ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, null);

        //Forwards
        MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);

        //ceq
        CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(device.getLocalIp(), device.getTransport());

        CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(3, Request.INVITE);
        request = SipFactory.getInstance().createMessageFactory().createRequest(requestLine, Request.INVITE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwards);

        //User-Agent
        request.addHeader(SipUtils.createUserAgentHeader());

        // Contact
        Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory().createSipURI(sipConfig.getId(), IpPortUtil.concatenateIpAndPort(NetUtil.getLocalhostStr(), String.valueOf(sipConfig.getPort()))));
        request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));

        // Subject
//        SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader(String.format("%s:%s,%s:%s", device.getDeviceId(), ssrc, sipConfig.getId(), 0));

        //级联Subject 具体的设备id
        SubjectHeader subjectHeader = SipFactory.getInstance().createHeaderFactory().createSubjectHeader("34020000001110000002");
        request.addHeader(subjectHeader);

        // Content-Type
        ContentTypeHeader contentTypeHeader = SipFactory.getInstance().createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP");
        request.setContent(content, contentTypeHeader);

        // 3.发送INVITE请求
        sipSender.transmitRequest(request);

        log.info("[发送INVITE] deviceId: {}->{}", deviceId, device.getHostAddress());

        return StrUtil.format("rtsp://{}:{}/rtp/{}", mediaConfig.getIp(), mediaConfig.getRtspPort(), "34020000001110000002");

    }
}
